package com.biwin.module.jwt.starter.session;

import com.biwin.core.api.session.ISessionProvider;
import com.biwin.core.main.session.BwAbstractSessionManager;
import com.biwin.module.jwt.api.enums.TokenManagerPolicy;
import com.biwin.module.jwt.api.properties.BiWinJwtProperties;
import com.biwin.module.security.api.vo.BwUserDetailVo;
import org.springframework.security.web.authentication.session.SessionAuthenticationException;
import org.springframework.stereotype.Component;

/**
 * BiWin Custom Session Manager with Redis
 *
 * @author biwin
 * @since 0.0.1
 */
@Component
public class BwRedisSessionManager<T extends BwUserDetailVo> extends BwAbstractSessionManager<T> {

    private final ISessionProvider<BwUserDetailVo> sessionProvider;

    private final BiWinJwtProperties jwtProperties;

    public BwRedisSessionManager(ISessionProvider sessionProvider, BiWinJwtProperties jwtProperties) {
        this.sessionProvider = sessionProvider;
        this.jwtProperties = jwtProperties;
        super.setSessionProvider(sessionProvider);
    }

    /**
     * 注册登录信息
     *
     * @param principal
     */
    @Override
    public void register(BwUserDetailVo principal) {
        // token 创建策略
        handlerSessionCreatePolicy(principal.getUsername());

        principal.setToken(sessionProvider.createJwtToken(principal, jwtProperties.getTtl()));

    }


    /**
     * 处理 jwt 配置的创建策略
     * <p>
     * 目前 token 创建策略有两种:
     * <p>
     * ONLY_FIRST: 则表示不管同是在线人数是几,都只能在线最多 maxNum 的人数,且无法被覆盖.<br/>
     * 如果在线用户数已达到 maxNum的值时,将无法再继续登录.
     * <p>
     * ONLY_LAST: 则表示不管同时在线人数是几,都允许最多同时 maxNum 的人数在线.<br/>
     * 如果在线用户数已达到 maxNUm 的值时,第一个登录的用户会被 maxNum+1 的登录挤下线.
     */
    private void handlerSessionCreatePolicy(String username) {
        TokenManagerPolicy.Create createTokenPolicy = jwtProperties.getCreateTokenPolicy();
        if (createTokenPolicy == TokenManagerPolicy.Create.ONLY_FIRST) {
            if (!sessionProvider.checkMaxNum(username)) {
                throw new SessionAuthenticationException("当前账户已超过最大同时在线数,无法登录!");
            }
        } else {
            if (!sessionProvider.checkMaxNum(username)) {
                sessionProvider.logoutFirstToken(username);
            }
        }
    }
}
